<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        function defineReactive(obj, key, val) {
            const dep = new Dep();

            Object.defineProperty(obj, key, {
                enumerable: true,
                configurable: true,
                get: function() {
                    if (Dep.target) {
                        //收集依赖 等同于  dep.addSub(Dep.target)
                        dep.depend()
                    }
                    return val;
                },
                set: function(newVal) {
                    if (newVal === val || (newVal !== newVal && val !== val)) {
                        return;
                    }
                    val = newVal;
                    //发布改变
                    dep.notify();
                }
            });
        }

        // 代码 1.2
        class Dep {
            constructor() {
                //订阅的信息
                this.subs = [];
            }

            addSub(sub) {
                this.subs.push(sub);
            }

            removeSub(sub) {
                remove(this.subs, sub);
            }

            //此方法的作用等同于 this.subs.push(Watcher);
            depend() {
                    if (Dep.target) {
                        Dep.target.addDep(this);
                    }
                }
                //这个方法就是发布通知了 告诉你 有改变啦
            notify() {
                const subs = this.subs.slice()
                for (let i = 0, l = subs.length; i < l; i++) {
                    subs[i].update();
                }
            }
        }
        Dep.target = null;

        //代码 1.4

        const obj = {}; //这一句是不是感觉很熟悉  就相当于初始化vue的data ---- data:{obj:{}};

        //低配的不能再低配的watcher对象（源码中是一个类，我这用一个对象代替了）
        const watcher = {
                addDep: function(dep) {
                    dep.addSub(this);
                },
                update: function() {
                    html();
                }
            }
            //假装这个是渲染页面的
        function html() {
            document.querySelector('body').innerHTML = obj.html;
        }
        defineReactive(obj, 'html', 'how are you'); //定义响应式的数据

        Dep.target = watcher;
        html(); //第一次渲染界面
        Dep.target = null;
    </script>
</body>

</html>